package test;

import java.util.ArrayList;
import java.util.Map.Entry;

import plan.Belegung;
import plan.Plan;
import util.Interval;
import auftrag.Auftrag;
import auftrag.Operation;
import auftrag.Produkt;
import auftrag.Resource;
import auftrag.Variante;
import constraints.AllOrdersPlanned;
import constraints.DueDate;
import constraints.IConstraint;
import constraints.NoMachineOverload;
import constraints.OperationOrder;

public class Start {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ArrayList<Operation> mOps = new ArrayList<Operation>();
		ArrayList<Auftrag> Aufträge = new ArrayList<Auftrag>();
		
		Auftrag a = new Auftrag("A1", 5);
		Aufträge.add(a);
		
		Produkt p1 = new Produkt(a, "P1");
		Produkt p2 = new Produkt(a, "P2");
		Produkt p3 = new Produkt(a, "P3");
		
		a.addProduct(p1, 1);
		a.addProduct(p2, 1);
		a.addProduct(p3, 1);
		
		Resource r1 = new Resource("M1");
		Resource r2 = new Resource("M2");
		Resource r3 = new Resource("M3");
		Resource r4 = new Resource("M4");
		
		Variante p1v1 = new Variante(p1, "1");
		Variante p2v1 = new Variante(p2, "1");
		Variante p3v1 = new Variante(p3, "1");
		
		p1.addVariante(p1v1);
		p2.addVariante(p2v1);
		p3.addVariante(p3v1);
		
		Operation p1v1o1 = new Operation(p1v1, null,"P1_O1");
		Operation p1v1o2 = new Operation(p1v1, p1v1o1,"P1_O2");
		Operation p1v1o3 = new Operation(p1v1, p1v1o2,"P1_O3");
		
		
		p1v1.addOperation(p1v1o1);
		p1v1.addOperation(p1v1o2);
		p1v1.addOperation(p1v1o3);
		
		p1v1o1.addPossibleResource(r1, 2);
		p1v1o2.addPossibleResource(r2, 2);
		p1v1o3.addPossibleResource(r3, 3);
		
		Operation p2v1o1 = new Operation(p2v1, null,"P2_O1");
		Operation p2v1o2 = new Operation(p2v1, p2v1o1,"P2_O2");
		Operation p2v1o3 = new Operation(p2v1, p2v1o2,"P2_O3");
		
		
		p2v1.addOperation(p2v1o1);
		p2v1.addOperation(p2v1o2);
		p2v1.addOperation(p2v1o3);
		
		p2v1o1.addPossibleResource(r1, 3);
		p2v1o2.addPossibleResource(r4, 2);
		p2v1o3.addPossibleResource(r2, 3);
		
		Operation p3v1o1 = new Operation(p3v1, null, "P3_O1");
		Operation p3v1o2 = new Operation(p3v1, p3v1o1, "P3_O2");
		Operation p3v1o3 = new Operation(p3v1, p3v1o2,"P3_O3");
		
		mOps.add(p1v1o1);
		mOps.add(p1v1o2);
		mOps.add(p1v1o3);
		mOps.add(p2v1o3);
		mOps.add(p2v1o1);
		mOps.add(p2v1o2);
		mOps.add(p3v1o3);
		mOps.add(p3v1o1);
		mOps.add(p3v1o2);
		
		
		
		p3v1.addOperation(p3v1o1);
		p3v1.addOperation(p3v1o2);
		p3v1.addOperation(p3v1o3);
		
		p3v1o1.addPossibleResource(r2, 1);
		p3v1o2.addPossibleResource(r4, 2);
		p3v1o3.addPossibleResource(r3, 1);
		
		a.print();
		
		System.out.println("========================================");
		System.out.println("PLANUNG");
		System.out.println("========================================");
		
		
		Plan p = new Plan();
		
		ArrayList<Operation> tmpList = mOps;
		while(tmpList.size() > 0){
			ArrayList<Operation> todoList = new ArrayList<Operation>();
			for(Operation o:tmpList){
				if(!planOperation(p, o))
					todoList.add(o);
			}
			tmpList = todoList;
			for(Operation o : todoList){
				System.out.println(o);
			}
		}
		p.addBelegung(new Belegung(a, p1, p1v1, p1v1o3, r2, new Interval(0,2)));
		p.print();
		
		IConstraint c1 = new AllOrdersPlanned();
		IConstraint c2 = new NoMachineOverload();
		IConstraint c3 = new OperationOrder();
		IConstraint c4 = new DueDate();
		
		if(c1.isMetBy(p, Aufträge)){
			System.out.println("Alle Aufträge eingeplant!");
		}
		if(c2.isMetBy(p,Aufträge)){
			System.out.println("Keine Doppelbelegung!");
		}
		if(c3.isMetBy(p, Aufträge)){
			System.out.println("Produktionsreihenfolge eingehalten!");
		}
		if(c4.isMetBy(p, Aufträge)){
			System.out.println("Alle Aufträge pünktlich abgearbeitet!");
		}
	}
	
	private static boolean planOperation(Plan p, Operation o){
		if(p.isPlanned(o))
			return true;
		System.out.println("Plan Operation: "+o);
		Resource r = null;
		int d = 0;
		for(Entry <Resource, Integer>e : o.getResources().entrySet()){
			r = e.getKey();
			d = e.getValue();
			break;
		}
		if(r!=null){
			boolean bPlan = true;
			if(o.getPreviousOperation() != null && !p.isPlanned(o.getPreviousOperation())){
				bPlan = planOperation(p, o.getPreviousOperation());
			}
			if(bPlan){
				Interval i = p.getUnoccupiedInterval(o, r, d);
				if(i != null)
					return p.addBelegung(new Belegung(o.getParent().getParent().getParent(), o.getParent().getParent(), o.getParent(), o, r, i));
			}
		}
		return false;
	}

}
